home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
alpha.arc
/
AX25CMD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-07-24
|
12KB
|
555 lines
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "ax25.h"
#include "timer.h"
#include "iface.h"
#include "lapb.h"
#include "cmdparse.h"
#include "session.h"
char *ax25states[] = {
"Disconnected",
"Conn pending",
"Disc pending",
"Connected",
"Recovery",
"Frame Reject",
};
int domycall(),dodigipeat(),doaxstat(),dot1(),dot2(),dot3(),domaxframe(),
doaxwindow(),dopaclen(),don2(),doaxreset(),dopthresh();
static struct cmds axcmds[] = {
"digipeat", dodigipeat, 0, NULLCHAR, NULLCHAR,
"maxframe", domaxframe, 0, NULLCHAR, NULLCHAR,
"mycall", domycall, 0, NULLCHAR, NULLCHAR,
"paclen", dopaclen, 0, NULLCHAR, NULLCHAR,
"pthresh", dopthresh, 0, NULLCHAR, NULLCHAR,
"reset", doaxreset, 2, "ax25 reset <axcb>", NULLCHAR,
"retry", don2, 0, NULLCHAR, NULLCHAR,
"status", doaxstat, 0, NULLCHAR, NULLCHAR,
"t1", dot1, 0, NULLCHAR, NULLCHAR,
"t2", dot2, 0, NULLCHAR, NULLCHAR,
"t3", dot3, 0, NULLCHAR, NULLCHAR,
"window", doaxwindow, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0, "ax25 subcommands: digipeat maxframe mycall paclen reset retry status\n\tt1 t2 t3 window", NULLCHAR,
};
/* Multiplexer for top-level ax25 command */
doax25(argc,argv)
int argc;
char *argv[];
{
return subcmd(axcmds,argc,argv);
}
static
doaxreset(argc,argv)
int argc;
char *argv[];
{
struct ax25_cb *axp;
extern char notval[];
axp = (struct ax25_cb *)htol(argv[1]);
if(!ax25val(axp)){
printf(notval);
return 1;
}
reset_ax25(axp);
return 0;
}
/* Display AX.25 link level control blocks */
static
doaxstat(argc,argv)
int argc;
char *argv[];
{
register int i;
register struct ax25_cb *axp;
char tmp[10];
extern char notval[];
if(argc < 2){
printf(" &AXB IF Snd-Q Rcv-Q Remote State\n");
for(i=0;i<NHASH;i++){
for(axp = ax25_cb[i];axp != NULLAX25; axp = axp->next){
pax25(tmp,&axp->addr.dest);
printf("%8lx %-5s%-8d%-8d%-10s%s\n",
(long)axp,axp->interface->name,
len_q(axp->txq),len_mbuf(axp->rxq),
tmp,ax25states[axp->state]);
}
}
return 0;
}
axp = (struct ax25_cb *)htol(argv[1]);
if(!ax25val(axp)){
printf(notval);
return 1;
}
dumpstat(axp);
return 0;
}
/* Dump one control block */
static
dumpstat(axp)
register struct ax25_cb *axp;
{
char tmp[10];
int i;
if(axp == NULLAX25 || axp->interface == NULLIF)
return;
printf("&AXB IF Remote RB V(S) V(R) Unack P Retry State\n");
pax25(tmp,&axp->addr.dest);
printf("%4x %-5s%-9s",(int)axp,axp->interface->name,tmp);
putchar(axp->rejsent ? 'R' : ' ');
putchar(axp->remotebusy ? 'B' : ' ');
printf(" %4d %4d",axp->vs,axp->vr);
printf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
printf(" %02u/%02u",axp->retries,axp->n2);
printf(" %s\n",ax25states[axp->state]);
printf("T1: ");
if(run_timer(&axp->t1))
printf("%lu",(axp->t1.start - axp->t1.count) * MSPTICK);
else
printf("stop");
printf("/%lu ms; ",axp->t1.start * MSPTICK);
printf("T2: ");
if(run_timer(&axp->t2))
printf("%lu",(axp->t2.start - axp->t2.count) * MSPTICK);
else
printf("stop");
printf("/%lu ms; ",axp->t2.start * MSPTICK);
printf("T3: ");
if(run_timer(&axp->t3))
printf("%lu",(axp->t3.start - axp->t3.count) * MSPTICK);
else
printf("stop");
printf("/%lu ms\n",axp->t3.start * MSPTICK);
if(axp->addr.ndigis == 0)
return;
printf("Digipeaters:");
for(i=0;i<axp->addr.ndigis;i++){
pax25(tmp,&axp->addr.digis[i]);
printf(" %s",tmp);
}
printf("\n");
}
/* Display or change our AX.25 address */
static
domycall(argc,argv)
int argc;
char *argv[];
{
char buf[15];
if(argc < 2){
pax25(buf,&mycall);
printf("%s\n",buf);
return 0;
}
if(setcall(&mycall,argv[1]) == -1)
return -1;
mycall.ssid |= E;
return 0;
}
/* Control AX.25 digipeating */
static
dodigipeat(argc,argv)
int argc;
char *argv[];
{
extern int digipeat;
if(argc == 1) {
printf("digipeat %s\n",digipeat ? "on" : "off");
} else {
if(strcmp(argv[1],"on") == 0)
digipeat = 1;
else
digipeat = 0;
}
}
/* Set retransmission timer */
static
dot1(argc,argv)
int argc;
char *argv[];
{
extern int16 t1init;
if(argc == 1) {
printf("T1 %lu ms\n",(long)t1init * MSPTICK);
} else {
t1init = atol(argv[1]) / MSPTICK;
}
}
/* Set acknowledgement delay timer */
static
dot2(argc,argv)
int argc;
char *argv[];
{
extern int16 t2init;
if(argc == 1) {
printf("T2 %lu ms\n",(long)t2init * MSPTICK);
} else {
t2init = atol(argv[1]) / MSPTICK;
}
}
/* Set idle timer */
static
dot3(argc,argv)
int argc;
char *argv[];
{
extern int16 t3init;
if(argc == 1) {
printf("T3 %lu ms\n",(long)t3init * MSPTICK);
} else {
t3init = atol(argv[1]) / MSPTICK;
}
}
/* Set retry limit count */
static
don2(argc,argv)
int argc;
char *argv[];
{
extern int16 n2;
if(argc == 1) {
printf("Retry %u\n",n2);
} else {
n2 = atoi(argv[1]);
}
}
/* Set maximum number of frames that will be allowed in flight */
static
domaxframe(argc,argv)
int argc;
char *argv[];
{
extern int16 maxframe;
if(argc == 1) {
printf("Maxframe %u\n",maxframe);
} else {
maxframe = atoi(argv[1]);
}
}
/* Set maximum length of I-frame data field */
static
dopaclen(argc,argv)
int argc;
char *argv[];
{
extern int16 paclen;
if(argc == 1) {
printf("Paclen %u\n",paclen);
} else {
paclen = atoi(argv[1]);
}
}
/* Set size of I-frame above which polls will be sent after a timeout */
static
dopthresh(argc,argv)
int argc;
char *argv[];
{
extern int16 pthresh;
if(argc == 1) {
printf("Pthresh %u\n",pthresh);
} else {
pthresh = atoi(argv[1]);
}
}
/* Set high water mark on receive queue that triggers RNR */
static
doaxwindow(argc,argv)
int argc;
char *argv[];
{
extern int16 axwindow;
if(argc == 1) {
printf("Axwindow %u\n",axwindow);
} else {
axwindow = atoi(argv[1]);
}
}
/* End of ax25 subcommands */
/* Initiate interactive AX.25 connect to remote station */
doconnect(argc,argv)
int argc;
char *argv[];
{
void ax_rx(),ax_tx(),ax_state();
int ax_parse();
struct ax25_addr dest;
struct ax25 addr;
struct ax25_cb *open_ax25();
struct interface *ifp;
struct session *s;
extern int16 axwindow;
int i;
for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
if(strcmp(argv[1],ifp->name) == 0)
break;
if(ifp == NULLIF){
printf("Interface %s unknown\n",argv[1]);
return 1;
}
setcall(&dest,argv[2]);
/* See if a session already exists */
for(s = sessions; s < &sessions[nsessions]; s++){
if(s->type == AX25TNC
&& addreq(&s->cb.ax25_cb->addr.dest,&dest)){
#if (defined(MAC) || defined(AMIGA))
printf("Session %lu to %s already exists\n",
#else
printf("Session %u to %s already exists\n",
#endif
s - sessions,argv[2]);
return 1;
}
}
/* Allocate a session descriptor */
if((s = newsession()) == NULLSESSION){
printf("Too many sessions\n");
return 1;
}
if((s->name = malloc((unsigned)strlen(argv[2])+1)) != NULLCHAR)
strcpy(s->name,argv[2]);
s->type = AX25TNC;
s->parse = ax_parse;
current = s;
ASSIGN(addr.source,mycall);
setcall(&addr.dest,argv[2]);
for(i=3; i < argc; i++)
setcall(&addr.digis[i-3],argv[i]);
addr.ndigis = i - 3;
s->cb.ax25_cb = open_ax25(&addr,axwindow,ax_rx,ax_tx,ax_state,ifp,(char *)s);
go();
return 0;
}
/* Display changes in AX.25 state */
void
ax_state(axp,old,new)
struct ax25_cb *axp;
int old,new;
{
struct session *s;
s = (struct session *)axp->user;
if(current != NULLSESSION && current->type == AX25TNC && current == s){
/* Don't print transitions between CONNECTED and RECOVERY */
if(new != RECOVERY && !(old == RECOVERY && new == CONNECTED))
printf("%s\n",ax25states[new]);
if(new == DISCONNECTED)
cmdmode();
fflush(stdout);
}
if(new == DISCONNECTED){
axp->user = NULLCHAR;
freesession(s);
}
}
/* Handle typed characters on AX.25 connection */
int
ax_parse(buf,cnt)
char *buf;
int16 cnt;
{
struct mbuf *bp;
register char *cp;
char c;
if(current == NULLSESSION || current->type != AX25TNC)
return; /* "can't happen" */
/* If recording is on, record outgoing stuff too */
if(current->record != NULLFILE)
fwrite(buf,1,cnt,current->record);
/* Allocate buffer and start it with the PID */
bp = alloc_mbuf(cnt+1);
*bp->data = PID_FIRST | PID_LAST | PID_NO_L3;
bp->cnt++;
/* Copy keyboard buffer to output, stripping line feeds */
cp = bp->data + 1;
while(cnt-- != 0){
c = *buf++;
if(c != '\n'){
*cp++ = c;
bp->cnt++;
}
}
send_ax25(current->cb.ax25_cb,bp);
}
/* Handle new incoming terminal sessions
* This is the default receive upcall function, used when
* someone else connects to us
*/
void
ax_incom(axp,cnt)
register struct ax25_cb *axp;
int16 cnt;
{
struct session *s;
char remote[10];
void ax_rx(),ax_state(),ax_tx();
pax25(remote,&axp->addr.dest);
if((s = newsession()) == NULLSESSION){
/* Out of sessions */
disc_ax25(axp);
return;
}
s->type = AX25TNC;
s->name = malloc((int16)strlen(remote)+1);
s->cb.ax25_cb = axp;
s->parse = ax_parse;
strcpy(s->name,remote);
axp->r_upcall = ax_rx;
axp->s_upcall = ax_state;
axp->t_upcall = ax_tx;
axp->user = (char *)s;
#if (defined(MAC) || defined(AMIGA))
printf("\007Incoming AX25 session %lu from %s\n",s - sessions,remote);
#else
printf("\007Incoming AX25 session %u from %s\n",s - sessions,remote);
#endif
fflush(stdout);
}
/* Handle incoming terminal traffic */
void
ax_rx(axp,cnt)
struct ax25_cb *axp;
int16 cnt;
{
register struct mbuf *bp;
struct mbuf *recv_ax25();
char c;
/* Hold output if we're not the current session */
if(mode != CONV_MODE || current == NULLSESSION
|| current->type != AX25TNC || current->cb.ax25_cb != axp)
return;
if((bp = recv_ax25(axp,cnt)) == NULLBUF)
return;
/* Display received characters, translating CR's to CR/LF */
while(bp != NULLBUF){
while(bp->cnt-- != 0){
c = *bp->data++;
if(c == '\r')
c = '\n';
putchar(c);
if(current->record){
#ifndef UNIX
if(c == '\n')
fputc('\r',current->record);
#endif
fputc(c,current->record);
}
}
bp = free_mbuf(bp);
}
if(current->record)
fflush(current->record);
fflush(stdout);
}
/* Handle transmit upcalls. Used only for file uploading */
void
ax_tx(axp,cnt)
struct ax25_cb *axp;
int16 cnt;
{
register char *cp;
struct session *s;
register struct mbuf *bp;
int16 size;
int c;
if((s = (struct session *)axp->user) == NULLSESSION
|| s->upload == NULLFILE)
return;
while(cnt != 0){
size = min(cnt,axp->paclen+1);
if((bp = alloc_mbuf(size)) == NULLBUF)
break;
cp = bp->data;
/* Start with the PID */
*cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
bp->cnt++;
/* Now send data characters, translating between local
* keyboard end-of-line sequences and the (unwritten)
* AX.25 convention, which is carriage-return only
*/
while(bp->cnt < size){
if((c = getc(s->upload)) == EOF)
break;
#ifdef MSDOS
/* MS-DOS gives cr-lf */
if(c == '\n')
continue;
#endif
#if (defined(UNIX) || defined(MAC) || defined(AMIGA))
/* These give lf only */
if(c == '\n')
c = '\r';
#endif
*cp++ = c;
bp->cnt++;
}
if(bp->cnt > 1) {
send_ax25(axp,bp);
} else {
/* Empty frame, don't bother sending */
free_p(bp);
break;
}
cnt -= bp->cnt;
}
if(cnt != 0){
/* Error or end-of-file */
fclose(s->upload);
s->upload = NULLFILE;
free(s->ufile);
s->ufile = NULLCHAR;
}
}